<div id="operationsPage" x-data="alpineOperations()" x-init="initOperations()"
     xmlns="http://www.w3.org/1999/html"
     @resize.window="getOperationsMenuCaretDisplay()">
    <div>
        <div>
            <div x-ref="operationsHeader">
                <h2>Operations</h2>
                <p>
                    Start a new operation or review previous ones here.
                </p>
            </div>
            <hr>
        </div>

        <div>
            <div class="is-flex is-flex-direction-row operations-dashboard">
                <div class="is-flex is-flex-direction-column pb-0 my-2"
                     x-bind:class="{'operations-menu-set-width': selectedOperation}">
                    <div class="pl-0 is-flex is-align-content-flex-start mb-2"
                         x-data="{startOperation: EMPTY_OPERATIONS_OBJECT}">
                        <div>
                            <div class="field has-addons">
                                <div class="control has-icons-left">
                                    <input class="input is-small"
                                           id="op-search"
                                           placeholder="Find an operation..."
                                           x-ref="search"
                                           x-on:keyup="filterOperations($el.value)">
                                    <span class="icon is-small is-left">
                                        <em class="fas fa-search"></em>
                                    </span>
                                </div>
                                <div class="control">
                                    <a class="button is-small"
                                       x-on:click="filterOperations(''); searchInput = ''; $refs.search.value=''">
                                        <span class="icon is-small is-right">
                                            <em class="fas fa-times"></em>
                                        </span>
                                    </a>
                                </div>
                            </div>
                        </div>
                        <div>&nbsp;&nbsp;</div>
                        <button x-bind:disabled="!(searchInput && filteredOperations.length === 0)"
                                title="creates a new operation based on the last created operation settings "
                                class="button is-primary is-small"
                                x-on:click="addOperation(true, startOperation)"><em class="pr-1 fas fa-plus"></em>
                            Quick Add
                        </button>
                        <button title="add operation" class="ml-2 button is-primary is-small"
                                x-on:click="openModal = 'addOperation'; getAgents()"><em class="pr-1 fas fa-plus"></em>
                            Create Operation
                        </button>
                        <template x-if="selectedOperation">
                            <button title="download reports" class="ml-2 button is-primary is-small"
                                    x-on:click="openModal = 'showDownloadMenu'"><em class="pr-1 fas fa-arrow-down"></em>
                                Download
                            </button>
                        </template>
                        <div class="is-flex is-justify-content-center pt-2"></div>
                    </div>
                    <div class="is-flex is-flex-direction-row is-align-items-center">
                        <div class="is-flex is-flex-direction-row is-justify-content-flex-start operation-menu-container">
                            <template x-if="filteredOperations.length < 1">
                                <em class="is-flex is-justify-content-center">No operations available; click on the
                                    'Create Operation' button to get started.</em>
                            </template>
                            <template x-for="op in filteredOperations" :key="op.id">
                                <button class="no-style operation-menu-links"
                                        x-bind:title="op.name + ' has ' + op.chain.length + ' decisions'"
                                        x-on:click="selectedOperation = op; getOperations(); getOperation()">
                                    <em x-show="selectedOperationID !== op.id" class="far fa-folder">
                                        <span class="decisionsIcon" x-text="op.chain.length"></span></em>
                                    <em x-show="selectedOperationID === op.id" class="far fa-folder-open"></em>
                                    <span class="operation-name" x-text="op.name"></span>
                                    <span class="readable-time" x-text="getHumanFriendlyTimeISO8601(op.start ? op.start : '')"></span>
                                </button>
                            </template>
                        </div>
                        <template x-if="showOperationsMenuCaret">
                            <div class="ml-2 scroll-more-caret">
                                <em class="fas fa-angle-right"></em>
                            </div>
                        </template>
                    </div>
                </div>
                <template x-if="selectedOperation">
                    <div x-show="selectedOperationID"
                         class="is-flex is-flex-direction-column mx-5">
                        <div class="is-flex is-flex-direction-row is-justify-content-center ml-5">
                            <div class="mr-6">
                                <h3 class="my-1 is-size-4" x-text="selectedOperation.name"></h3>
                                <h2 class="is-size-6 has-text-weight-normal mb-5 mt-0">Operation</h2>
                            </div>
                            <div class="mr-6">
                                <h3 class="my-1 is-size-5" x-text="selectedOperation.state"></h3>
                                <h2 class="is-size-7 has-text-weight-normal mb-5 mt-0">Current state</h2>
                            </div>
                            <div>
                                <h3 class="decisionsDisplay my-1 is-size-5"
                                    x-text="selectedOperation.chain.length"></h3>
                                <h2 class="is-size-7 has-text-weight-normal mb-5 mt-0">Decisions</h2>
                            </div>
                        </div>
                        <div class="controls-container is-flex is-justify-content-center is-align-items-center">
                            <button x-bind:disabled="!isOperationRunning" class="button no-style is-large"
                                    x-on:click="updateOperation('state', 'cleanup')"><em
                                    title="stop" class="fas fa-stop"></em></button>
                            <template x-if="selectedOperation.state ==='running'">
                                <button x-bind:disabled="!isOperationRunning"
                                        class="button no-style is-larger"
                                        x-on:click="updateOperation('state', 'paused')"><em
                                        title="pause" class="fas fa-pause-circle"></em></button>
                            </template>
                            <template x-if="selectedOperation.state !== 'running'">
                                <button x-bind:disabled="!isOperationRunning"
                                        class="button no-style is-larger"
                                        x-on:click="updateOperation('state', 'running')">
                                    <em title="run" class="fas fa-play-circle"></em></button>
                            </template>
                            <button x-bind:disabled="!isOperationRunning" class="button no-style is-medium"
                                    x-on:click="updateOperation('state', 'run_one_link')">
                                <em title="run one step" class="fas fa-play"><sub>1</sub></em></button>
                        </div>
                        <div class="is-flex is-justify-content-center pt-2 hover-opacity">
                            <button type="button" title="delete operation"
                                    class="mx-2 mt-2 button no-style"
                                    x-on:click="openModal = 'deleteOperationModal'"><em
                                    class="pr-1 fas fa-trash"></em>
                            </button>
                        </div>
                    </div>
                </template>
                <template x-if="selectedOperation">
                    <div x-show="selectedOperationID"
                         class="is-flex is-flex-direction-column is-flex-wrap-wrap">
                        <div class="mb-4 is-flex is-flex-direction-row is-flex-wrap-wrap">
                            <label x-show="false" for="operation-obfuscator" class="is-size-6">
                                Obfuscation method:
                            </label>
                            <template x-if="!isOperationRunning">
                                <div class="is-flex is-justify-content-center">
                                    <button class="is-small button is-rounded m-1"
                                            x-text="selectedOperation.obfuscator + ' obfuscation'"></button>
                                </div>
                            </template>
                            <template x-if="isOperationRunning">
                                <div class="is-flex is-flex-direction-row is-flex-wrap-wrap is-justify-content-center pb-2"
                                     id="operation-obfuscator">
                                    <template x-for="o in OBFUSCATORS" :key="o.name">
                                        <button x-bind:class="selectedOperation.obfuscator === o.name ? '' : 'is-outlined has-text-white'"
                                                class="is-small button is-rounded is-primary m-1"
                                                x-on:click="updateOperation('obfuscator', o.name)"
                                                x-text="o.name">
                                        </button>
                                    </template>
                                </div>
                            </template>
                        </div>

                        <template x-if="isOperationRunning">
                            <div class="is-flex is-flex-direction-row is-justify-content-center is-align-items-center width-100">
                                <div class="toggleContainer">
                                    <label for="toggleAutonomous">Manual</label>
                                    <div class="toggleSwitch mx-2">
                                        <input type="checkbox"
                                               id="toggleAutonomous"
                                               x-model="selectedOperation.autonomous"
                                               x-bind:checked="Boolean(selectedOperation.autonomous) ? 'checked' : null"/>
                                        <span class="toggleSlider toggleSliderRound"
                                              title="Toggle operation to run autonomously"
                                              x-on:click="selectedOperation.autonomous = (selectedOperation.autonomous === 0) ? 1 : 0; updateOperation('autonomous', Number(selectedOperation.autonomous))"
                                              x-bind:class="Boolean(selectedOperation.autonomous) ? 'toggle-on' : 'toggle-off'">
                                                    <span x-bind:class="Boolean(selectedOperation.autonomous) ? 'toggle-slider-on' : 'toggle-slider-off'"></span>
                                                </span>
                                    </div>
                                    <label for="toggleAutonomous">Autonomous</label>
                                </div>
                            </div>
                        </template>

                        <template x-if="!isOperationRunning">
                            <div class="is-flex is-justify-content-center mt-5">
                                <em>Operation has finished running.</em>
                            </div>
                        </template>
                    </div>
                </template>
            </div>

            <template x-if="filteredOperations.length > 0 && !selectedOperation">
                <em class="is-flex is-justify-content-center">Click on an operation above to get started.</em>
            </template>

            <!--            TIMELINE-->
            <div>
                <template x-if="selectedOperation">
                    <div x-show="selectedOperationID">
                        <div class="navbar-divider mb-5 width-100"></div>
                        <template x-if="isOperationRunning">
                            <div class="is-flex is-flex-direction-row is-justify-content-space-between">
                                <div class="has-text-grey-light is-size-7">
                                    <em x-show="selectedOperation.chain.length > 0"><span
                                            class="has-text-grey-light"
                                            x-text="'Last ran ' + selectedOperation.chain[selectedOperation.chain.length-1]?.ability.name + ' (' + getLastDecideTime() + ')'"></span></em>
                                </div>
                                <div class="is-flex is-flex-direction-row is-justify-content-flex-end">
                                    <div class="mb-6 mr-4 text-align-right">
                                        <button title="add manual command" class="button is-primary is-small"
                                                x-on:click="addNewRow = true; getAgents(); setTimeout(() => {document.querySelector('#input-command').scrollIntoView()}, 2);">
                                            <em class="pr-1 fas fa-plus"></em>Manual
                                            Command
                                        </button>
                                    </div>
                                    <div class="mb-6 mr-4">
                                        <button title="add potential link" class="button is-primary is-small"
                                                x-on:click="openModal = 'addLink'; getAgents()"><em
                                                class="pr-1 fas fa-plus"></em>Potential
                                            Link
                                        </button>
                                    </div>
                                </div>
                            </div>
                        </template>
                        <div class="timeline-table">
                            <table class="table" @click.outside="selectedLink = null;">
                                <thead>
                                <tr class="table-header">
                                    <th class="decideColumn">Decide</th>
                                    <th id="link-status-header" class="statusColumn csv-exclude pl-4" title="Link Status Indicator">
                                        Status
                                    </th>
                                    <th class="infoColumn">Link/Ability Name</th>
                                    <th>Agent #paw</th>
                                    <th>Host</th>
                                    <th>pid</th>
                                    <th>Link Command</th>
                                    <th>Link Output</th>
                                    <th title="Link Actions" class="csv-exclude"></th>
                                </tr>
                                </thead>

                                <template x-if="selectedOperation.chain.length === 0">
                                    <tbody>
                                    <tr class="csv-exclude">
                                        <td colspan="9" class="has-text-centered"><em>No links––click the buttons on the right to add
                                            commands/links.</em>
                                        </td>
                                    </tr>
                                    </tbody>
                                </template>
                                <template x-for="(link, index) in selectedOperation.chain" :key="link.id">
                                    <tbody>
                                    <tr x-bind:id="link.id"
                                        x-on:click="selectedLink = link">
                                        <td class="decideColumn">
                                            <span class="has-text-grey-light" x-text="getReadableTime(link.decide)"></span>
                                        </td>
                                        <td class="linkStatusColumn csv-exclude" headers="link-status-header">
                                            <span x-bind:class="'linkStatus status-'+((link.status in LINK_STATUSES) ? LINK_STATUSES[link.status] : 'queued')"
                                                  x-bind:data-content="link.status in LINK_STATUSES ? LINK_STATUSES[link.status] : 'queued'"
                                                  x-bind:title="link.status in LINK_STATUSES ? LINK_STATUSES[link.status] : 'queued'"></span>
                                        </td>
                                        <td class="linkInfoColumn"
                                            x-text="link.ability.name + ((link.ability.cleanup) ? '(CLEANUP)' : '')"></td>

                                        <!--AGENT COLUMN-->
                                        <td class="agentDetails">
                                            <p x-show="!link.paw"><em>n/a</em></p>
                                            <p x-show="link.paw"><em x-text="link.paw"></em></p>
                                        </td>
                                        <td class="agentDetails">
                                            <p x-show="!link.host"><em>n/a</em></p>
                                            <p x-show="link.host"><em
                                                    x-text="link.host"></em></p>
                                        </td>
                                        <td class="agentDetails">
                                            <p x-show="!link.pid"><em>n/a</em></p>
                                            <p x-show="link.pid"><em
                                                    x-text="link.pid"></em></p>
                                        </td>

                                        <!--COMMAND COLUMN-->
                                        <td class="commandDetails">
                                            <template x-if="!isLinkEditable">
                                                <div class="is-flex is-justify-content-center is-flex-direction-column">
                                                    <button class="button is-primary is-small"
                                                            x-on:click="getLink(link); openModal='showCommand'"
                                                            title="view output">View Command
                                                    </button>
                                                </div>
                                            </template>
                                            <template x-if="isLinkEditable">
                                                <div class="is-flex is-align-items-flex-start is-justify-content-flex-start is-flex-direction-column">
                                                    <label x-show="false" for="edit-command">Edit command</label>
                                                    <textarea id="edit-command"
                                                              class="code mb-2"
                                                              contenteditable
                                                              x-model="editableCommand"
                                                              spellcheck="false"></textarea>

                                                    <!-- BUTTONS TO MANUALLY EXECUTE (APPROVE/DISCARD) COMMAND-->
                                                    <div class="is-flex is-justify-content-space-between">
                                                        <button type="button"
                                                                class="button is-small mr-3"
                                                                x-on:click="updateLink(-2)">
                                                            Discard
                                                        </button>
                                                        <button type="button"
                                                                class="button is-primary is-small"
                                                                x-on:click="updateLink(-3, editableCommand)">
                                                            Approve
                                                        </button>
                                                    </div>
                                                </div>
                                            </template>
                                        </td>

                                        <!--OUTPUT/FACTS COLUMN-->
                                        <td class="outputDetails">
                                            <template x-if="link.output !== 'True'">
                                                <p class="is-size-7">No output available.</p>
                                            </template>
                                            <template x-if="link.output === 'True'">
                                                <div>
                                                    <button class="button is-primary is-small"
                                                            x-on:click="getLink(link); openModal='showOutput'"
                                                            title="view output">View Output
                                                    </button>
                                                </div>
                                            </template>
                                        </td>

                                        <td class="csv-exclude">
                                            <button x-show="selectedLink === link && isOperationRunning && !(link.status in LINK_STATUSES)"
                                                    type="button" title="delete link"
                                                    class="button is-primary is-small ml-2"
                                                    x-on:click="openModal = 'deleteLinkModal'"><em
                                                    class="pr-1 fas fa-trash"></em>Discard Link
                                            </button>
                                        </td>
                                    </tr>
                                    </tbody>
                                </template>

                                <!--                                NEW ROW TO ADD MANUAL COMMAND-->
                                <template x-if="addNewRow">
                                    <tbody>
                                    <tr class="csv-exclude" x-data="{manualCommand: EMPTY_MANUAL_COMMAND_OBJECT}">
                                        <template x-if="selectedOperation.host_group.length < 1">
                                            <td colspan="9" class="has-text-right"><em>No agents running. Add an agent
                                                to run an operation.</em></td>
                                        </template>
                                    </tr>

                                    <template x-if="selectedOperation.host_group.length > 0">
                                        <tr class="csv-exclude" x-data="{manualCommand: EMPTY_MANUAL_COMMAND_OBJECT}">
                                            <td></td>
                                            <td></td>
                                            <td>New Manual Command</td>
                                            <td>
                                                <label x-show="false" for="manual-agent">Choose an agent:</label>
                                                <div class="select is-small my-2 ml-3">
                                                    <select id="manual-agent" x-model="selectedAgentIndex"
                                                            x-on:change="getAgent(selectedAgent.paw)" required>
                                                        <option value="" disabled>Choose agent</option>
                                                        <template x-for="(agent, index) in selectedOperation.host_group"
                                                                  :key="agent.paw">
                                                            <option x-bind:selected="index === 0"
                                                                    :value="index"
                                                                    x-text="agent.display_name + '-' + agent.paw"></option>
                                                        </template>
                                                    </select>
                                                </div>
                                            </td>
                                            <td>
                                                <div class="select is-small my-2 ml-3">
                                                    <select x-model="manualCommand.executor.name"
                                                            id="manual-executors"
                                                            class="executor-selector">
                                                        <option value="" disabled>Choose executor</option>
                                                        <template x-for="(executor, index) in selectedAgentExecutors"
                                                                  :key="executor.executor">
                                                            <option x-bind:selected="index === 0"
                                                                    x-text="executor.display"
                                                                    :value="executor.executor"></option>
                                                        </template>
                                                    </select>
                                                </div>
                                            </td>
                                            <td colspan="2">
                                                <label x-show="false" for="input-command">Type manual command:</label>
                                                <div class="is-flex is-align-items-flex-end is-justify-content-center is-flex-direction-column">
                                                <textarea x-model="manualCommand.executor.command"
                                                          class="input executor-command"
                                                          id="input-command"
                                                          type="text"
                                                          spellcheck="false"
                                                          contenteditable
                                                          required></textarea>
                                                </div>
                                            </td>
                                            <td class="is-flex is-justify-content-center is-flex-direction-column">
                                                <button type="button"
                                                        class="button is-primary is-small my-2"
                                                        x-on:click="addManualCommand(manualCommand)">
                                                    Add Command
                                                </button>
                                                <button type="button"
                                                        class="button is-small"
                                                        x-on:click="addNewRow = false">
                                                    Cancel
                                                </button>
                                            </td>
                                        </tr>
                                    </template>
                                    </tbody>
                                </template>
                            </table>
                        </div>

                        <!--                                ADD COMMAND/LINK BUTTONS-->
                        <template x-if="isOperationRunning">
                            <div class="is-flex is-flex-direction-row is-justify-content-flex-end">
                                <div class="mb-6 mr-4 has-text-right">
                                    <button title="add manual command" class="button is-primary is-small"
                                            x-on:click="addNewRow = true; getAgents()">
                                        <em class="pr-1 fas fa-plus"></em>Manual
                                        Command
                                    </button>
                                </div>
                                <div class="mb-6 mr-4">
                                    <button title="add potential link" class="button is-primary is-small"
                                            x-on:click="openModal = 'addLink'; getAgents()"><em
                                            class="pr-1 fas fa-plus"></em>Potential
                                        Link
                                    </button>
                                </div>
                            </div>
                        </template>
                    </div>
                </template>
            </div>
        </div>

        <!--    MODALS      -->
        <template x-if="openModal">
            <div class="modal is-active" x-data="{ startOperation: EMPTY_OPERATIONS_OBJECT }">
                <div class="modal-background" @click="openModal = null"></div>

                <template x-if="openModal === 'showOutput'">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Output</p>
                        </header>
                        <section class="modal-card-body">
                            <template x-if="selectedLinkFacts?.length > 0">
                                <div class="mb-2">
                                    <p class="mt-3 mb-2">Facts:</p>
                                    <pre class="has-text-left white-space-pre-line">
                                        <template x-for="(fact, index) in selectedLinkFacts" :key="fact+index">
                                            <span class="has-background-warning has-text-black mr-2" x-text="fact"></span>
                                        </template>
                                    </pre>
                                </div>
                            </template>
                            <div>
                                <pre class="has-text-left white-space-pre-line" x-text="selectedLinkResults"></pre>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'showCommand'">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Command</p>
                        </header>
                        <section class="modal-card-body">
                            <div>
                                <pre class="has-text-left white-space-pre-line" x-text="selectedLinkCommand"></pre>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'addOperation'">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Start New Operation</p>
                        </header>
                        <section class="modal-card-body">
                            <div class="modal-form">
                                <div>
                                    <label for="op-name">Operation name</label>
                                    <div class="modal-form-fields">
                                        <input class="input is-small" id="op-name" type="text"
                                               x-model="startOperation.name" required>
                                    </div>
                                </div>
                                <div>
                                    <label for="basic-adversary"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Adversary']">Adversary</span></label>
                                    <div class="modal-form-fields" id="basic-adversary">
                                        <div class="select is-small my-2 ml-3">
                                            <select x-model="startOperation.adversary.adversary_id">
                                                <option value="" selected>No adversary (manual)</option>
                                                <template x-for="a in ADVERSARIES" :key="a.adversary_id">
                                                    <option x-on:click="isSelectedAdversaryRepeatable = a.has_repeatable_abilities"
                                                            :value="a.adversary_id"
                                                            x-text="a.name">
                                                    </option>
                                                </template>
                                            </select>
                                        </div>
                                    </div>
                                </div>

                                <div>
                                    <label for="autonomous-source"><span
                                            class="has-tooltip-multiline has-tooltip-top"
                                            x-bind:data-tooltip="usage['Fact source']">Fact source</span></label>
                                    <div class="modal-form-fields" id="autonomous-source">
                                        <div class="select is-small my-2 ml-3">
                                            <select x-model="startOperation.source.id">
                                                <template x-for="s in SOURCES" :key="s.id">
                                                    <option :value="s.id" x-text="s.name"></option>
                                                </template>
                                            </select>
                                        </div>
                                    </div>
                                </div>

                            </div>
                            <div class="modal-form-group-header">
                                <button type="button" class="button no-style heading pt-2"
                                        x-on:click="openModalForm.advanced = !openModalForm.advanced"
                                        x-bind:class="openModalForm.advanced ? 'expanded' : 'collapsed'">
                                    <span>Advanced</span>
                                    <span class="navbar-divider"></span>
                                </button>
                            </div>
                            <div class="modal-form" x-show="openModalForm.advanced">
                                <div>
                                    <label for="basic-groups"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Group']">Group</span></label>
                                    <div class="modal-form-fields"
                                         id="basic-groups">
                                        <button type="button"
                                                class="is-small button is-rounded is-primary m-1"
                                                x-bind:class="(startOperation.group === '') ? '' : 'is-outlined has-text-white'"
                                                x-on:click="startOperation.group = ''">
                                            all groups
                                        </button>
                                        <template x-for="(group, index) in agentGroups" :key="group">
                                            <button type="button"
                                                    class="is-small button is-rounded is-primary m-1"
                                                    x-bind:class="(startOperation.group === group) ? '' : 'is-outlined has-text-white'"
                                                    x-on:click="startOperation.group = group"
                                                    x-show="group !== ''"
                                                    x-text="group">
                                            </button>
                                        </template>
                                    </div>
                                </div>
                                <div>
                                    <label for="autonomous-planner"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Planner']">Planner</span></label>
                                    <div class="modal-form-fields">
                                        <div class="select is-small my-2 ml-3">
                                            <select id="autonomous-planner" x-model="startOperation.planner.id">
                                                <template x-for="p in PLANNERS" :key="p.id">
                                                    <option :value="p.id"
                                                            x-bind:data-allow-repeatable-abilities="p.allow_repeatable_abilities"
                                                            x-bind:disabled="(!p.allow_repeatable_abilities && isSelectedAdversaryRepeatable) ? 'true' : null"
                                                            x-text="p.name"></option>
                                                </template>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                                <div>
                                    <label for="stealth-obfuscator"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Obfuscators']">Obfuscators</span></label>
                                    <div class="modal-form-fields" id="stealth-obfuscator">
                                        <template x-for="o in OBFUSCATORS" :key="o.name">
                                            <button class="is-small button is-rounded is-primary m-1"
                                                    type="button"
                                                    x-bind:class="startOperation.obfuscator === o.name ? '' : 'is-outlined has-text-white'"
                                                    x-on:click="startOperation.obfuscator = o.name"
                                                    x-text="o.name">
                                            </button>
                                        </template>
                                    </div>
                                </div>
                                <div>
                                    <label for="autonomous-autonomous"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Autonomous']">Autonomous</span></label>
                                    <div class="modal-form-fields" id="autonomous-autonomous">
                                        <input type="radio" id="run-autonomously"
                                               x-model="startOperation.autonomous" value="1" checked>
                                        <label for="run-autonomously">Run autonomously</label>
                                        <input type="radio" id="manual-approval"
                                               x-model="startOperation.autonomous" value="0">
                                        <label for="manual-approval">Require manual approval</label>
                                    </div>
                                </div>

                                <div>
                                    <label for="autonomous-use_learning_parsers"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Parser']">Parser</span></label>
                                    <div class="modal-form-fields" id="autonomous-use_learning_parsers">
                                        <input type="radio" id="parsers-default"
                                               x-model="startOperation.use_learning_parsers" value="1" checked>
                                        <label for="parsers-default">Use default parsers</label>
                                        <input type="radio" id="parsers-no_default"
                                               x-model="startOperation.use_learning_parsers" value="0">
                                        <label for="parsers-no_default">Do not use default parsers</label>
                                    </div>
                                </div>

                                <div>
                                    <label for="basic-keep"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Auto-close']">Auto-close</span></label>
                                    <div class="modal-form-fields" id="basic-keep">
                                        <input type="radio" id="keep-open"
                                               x-model="startOperation.auto_close"
                                               value="0" checked>
                                        <label for="keep-open">Keep open forever</label>
                                        <input type="radio" id="auto-close"
                                               x-model="startOperation.auto_close"
                                               value="1">
                                        <label for="auto-close">Auto close operation</label>
                                    </div>
                                </div>
                                <div>
                                    <label for="basic-run"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Run immediately']">Run state</span></label>

                                    <div class="modal-form-fields" id="basic-run">
                                        <input type="radio" x-model="startOperation.state"
                                               id="run-immediately"
                                               value="running" checked>
                                        <label for="run-immediately">Run immediately</label>
                                        <input type="radio" x-model="startOperation.state"
                                               id="pause-on-start"
                                               value="paused">
                                        <label for="pause-on-start">Pause on start</label>
                                    </div>
                                </div>

                                <div>
                                    <label for="stealth-jitter"><span
                                            class="has-tooltip-multiline has-tooltip-top"
                                            x-bind:data-tooltip="usage['Jitter']">Jitter (sec/sec)</span></label>
                                    <div class="modal-form-fields" id="stealth-jitter">
                                        <input class="input"
                                               x-on:change.debounce.500ms="validateJitter(startOperation, jitterMin+'/'+jitterMax)"
                                               x-model="jitterMin"
                                               id="stealth-jitterMin"
                                               type="number"
                                               required
                                               pattern="[0-9]*"
                                               placeholder="2"/>
                                        <label class="input-hover-label" for="stealth-jitterMin">min</label>
                                        <span>/</span>
                                        <input class="input"
                                               x-on:change.debounce.500ms="validateJitter(startOperation, jitterMin+'/'+jitterMax)"
                                               x-model="jitterMax"
                                               id="stealth-jitterMax"
                                               type="number"
                                               required
                                               pattern="[0-9]*"
                                               placeholder="8"/>
                                        <label class="input-hover-label" for="stealth-jitterMax">max</label>
                                        <button type="button" class="button is-primary no-style reset"
                                                title="reset to default"
                                                x-on:click="jitterMin = 2; jitterMax = 8;">
                                            Reset
                                        </button>
                                    </div>
                                </div>
                                <div>
                                    <label for="stealth-queue"><span
                                            class="has-tooltip-multiline has-tooltip-top"
                                            x-bind:data-tooltip="usage['Visibility']">Visibility</span></label>
                                    <div class="modal-form-fields">
                                        <input x-model="startOperation.visibility"
                                               id="stealth-queue"
                                               type="range" value="50" min="1" max="100"
                                               x-on:change.once="toast('The higher the visibility number, the more risk you will take with your operation getting noticed by the defense.', true)">
                                        <span x-text="startOperation.visibility"></span>
                                    </div>
                                </div>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button type="button" class="button is-primary is-small"
                                                x-on:click="addOperation(false, startOperation)"
                                                x-text="schedule ? 'Schedule' : 'Start'"></button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'addLink'">
                    <div class="modal-card" x-init="getAbilities()">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Add New Potential Link</p>
                        </header>
                        <section class="modal-card-body">
                            <div class="modal-form">
                                <div>
                                    <label for="link-agent">Agent</label>
                                    <div class="modal-form-fields">
                                        <div class="select is-small my-2 ml-3">
                                            <select id="link-agent"
                                                    x-model="selectedAgentIndex"
                                                    x-on:change="getAgent(selectedAgent.paw); potentialLink.agent = selectedAgent">
                                                <template x-for="(agent, index) in selectedOperation.host_group"
                                                          :key="agent.paw">
                                                    <option :value="index"
                                                            x-bind:selected="index === 0"
                                                            x-text="agent.display_name + '-' + agent.paw"></option>
                                                </template>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                                <div>
                                    <label for="link-exec">Executor</label>
                                    <div class="modal-form-fields">
                                        <div class="select is-small my-2 ml-3">
                                            <select id="link-exec" x-model="potentialLink.executor"
                                                    x-on:change="filterAbilities(abilities)">
                                                <template x-for="(exec, index) of selectedAgentExecutors"
                                                          :key="exec.executor">
                                                    <option x-text="exec.display" :value="exec.executor"
                                                            x-bind:selected="index === 0"></option>
                                                </template>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                                <div>
                                    <label for="link-tactic">Tactic</label>
                                    <div class="modal-form-fields">
                                        <div class="select is-small my-2 ml-3">
                                            <select id="link-tactic"
                                                    x-model="potentialLink.tactic"
                                                    x-on:change="filterAbilities(abilities)">
                                                <option value="" default value="">All tactics</option>
                                                <template x-for="tactic in tacticFiltersList"
                                                          :key="tactic">
                                                    <option x-text="tactic"></option>
                                                </template>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                                <div>
                                    <label for="link-technique">Technique</label>
                                    <div class="modal-form-fields">
                                        <div class="select is-small my-2 ml-3">
                                            <select id="link-technique"
                                                    x-model="potentialLink.technique"
                                                    x-on:change="filterAbilities(abilities)">
                                                <option value="" default>All techniques</option>
                                                <template x-for="technique in techniqueFiltersList"
                                                          :key="technique">
                                                    <option x-text="technique"></option>
                                                </template>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="modal-results">
                                <div class="navbar-divider"></div>
                                <p class="is-flex is-justify-content-flex-end is-size-7"
                                   x-text="filteredAbilitiesList.length + ' potential link' + ((filteredAbilitiesList.length === 1) ? '' : 's')"></p>
                                <template x-if="filteredAbilitiesList">
                                    <ul class="ml-0">
                                        <template x-for="ability in filteredAbilitiesList"
                                                  :key="ability.ability_id">
                                            <li class="mb-4 abilities-list-item">
                                                    <span class="is-flex is-justify-content-space-between">
                                                        <span>
                                                            <p class="mb-0" x-text="ability.name"></p>
                                                        </span>
                                                        <span>
                                                            <button type="button"
                                                                    class="button is-primary is-small"
                                                                    x-bind:disabled="!isLinkAvailable(ability)"
                                                                    x-bind:title="!isLinkAvailable(ability) ? 'Link is unavailable or has been already added.' : ''"
                                                                    x-on:click="addPotentialLink(ability)">
                                                                Add Link
                                                            </button>
                                                        </span>
                                                    </span>
                                                <span class="ml-3">
                                                        <sub x-text="ability.description"></sub>
                                                    </span>
                                            </li>
                                        </template>
                                    </ul>
                                </template>
                                <template x-if="!filteredAbilitiesList"><p>Building potential links...</p>
                                </template>
                            </div>
                            <em x-show="showNotRepeatableText"
                                class="has-text-grey-light is-pulled-right is-size-7">Note:
                                Repeated links are not available for this operation</em>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'showDownloadMenu'">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Download Reports</p>
                        </header>
                        <section class="modal-card-body">
                            <div class="modal-form">
                                <div>
                                    <label for="agent-output-field">Agent output</label>
                                    <div class="modal-form-fields" id="agent-output-field">
                                        <input id="agent-output"
                                               x-bind:disabled="selectedReportType === 'csv'"
                                               type="checkbox"
                                               class="mr-1"
                                               x-model="isAgentOutputSelected">
                                        <label for="agent-output">include agent output</label>
                                    </div>
                                </div>
                                <div>
                                    <label for="report-type">Report type</label>
                                    <div class="modal-form-fields download-buttons-container" id="report-type">
                                        <input class="mr-1" type="radio" x-model="selectedReportType"
                                               value="full-report" id="full-report">
                                        <label for="full-report">Full Report</label>
                                        <input class="mr-1" type="radio" x-model="selectedReportType"
                                               value="event-logs" id="event-logs">
                                        <label for="event-logs">Event Logs</label>
                                        <input class="mr-1" type="radio" x-model="selectedReportType"
                                               value="csv" id="csv">
                                        <label for="csv">CSV</label>
                                    </div>
                                </div>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button type="button" class="button is-primary is-small"
                                                x-on:click="handleDownload()">
                                            Download
                                        </button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'deleteOperationModal' && selectedOperation">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Delete operation?</p>
                        </header>
                        <section class="modal-card-body">
                            <div class="modal-form">
                                <div>
                                    <p>Are you sure you want to delete the operation <em
                                            x-text="selectedOperation.name"></em>?</p>
                                </div>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                    <div class="level-item">
                                        <button type="button" class="button ml-2 is-small"
                                                x-on:click="openModal = null">
                                            Cancel
                                        </button>
                                    </div>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button type="button" class="button is-primary is-small"
                                                x-on:click="deleteOperation(); openModal = null;">
                                            Delete
                                        </button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'deleteLinkModal'">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Delete link?</p>
                        </header>
                        <section class="modal-card-body">
                            <div class="modal-form">
                                <div>
                                    <p>Are you sure you want to delete the link <em
                                            x-text="selectedLink.ability.name"></em>?</p>
                                </div>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                    <div class="level-item">
                                        <button type="button" class="button ml-2 is-small" x-on:click="openModal = null">
                                            Cancel
                                        </button>
                                    </div>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button type="button" class="button is-primary is-small"
                                                x-on:click="updateLink(-2); openModal = null;">
                                            Delete
                                        </button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>
            </div>
        </template>
    </div>
</div>

<script>
    function alpineOperations() {
        return {
            // CONSTANTS
            ENDPOINT: '/api/v2/operations',
            EXECUTOR_SHELLS: {
                psh: 'PS',
                sh: '$',
                zsh: '$'
            },
            LINK_STATUSES: {
                0: 'success',
                '-1': 'paused',
                1: 'failed',
                '-2': 'discarded',
                '-3': 'collect',
                '-4': 'untrusted',
                '-5': 'visible',
                124: 'timeout'
            },
            OBFUSCATORS: [],
            PLANNERS: [],
            ADVERSARIES: [],
            SOURCES: [],

            docs: '{{ usage | tojson }}'.toString().replace(/["\[\]]/g, '').split('}'),
            usage: {},
            agentGroups: '{{ groups | tojson }}'.toString().replace(/["\[\]]/g, '').split(','),
            selectedOperation: null,
            selectedAgentIndex: 0,
            isSelectedAdversaryRepeatable: false,
            selectedLink: null,
            selectedLinkResults: null,
            selectedLinkFacts: null,
            selectedLinkCommand: null,
            selectedReportType: 'full-report',
            isAgentOutputSelected: false,
            openModal: null,
            openModalForm: {
                advanced: false
            },
            operations: [],
            filteredOperations: [],
            searchInput: '',
            jitterMin: 2,
            jitterMax: 8,
            potentialLink: {
                agent: '',
                executor: '',
                tactic: '',
                technique: '',
            },
            tacticFiltersList: [],
            techniqueFiltersList: [],
            abilities: [],
            filteredAbilitiesList: [],
            schedule: '',
            editableCommand: null,
            showOperationsMenuCaret: true,
            addNewRow: false,
            addedTechniquesIDs: new Set(),

            get EMPTY_OPERATIONS_OBJECT() {
                return {
                    name: '',
                    group: '',
                    adversary: { adversary_id: '' },
                    auto_close: 0,
                    state: 'running',
                    autonomous: 1,
                    planner: { id: 'atomic' },
                    source: { id: 'basic' },
                    use_learning_parsers: 1,
                    obfuscator: 'plain-text',
                    jitter: '2/8',
                    visibility: '51',
                };
            },

            get EMPTY_MANUAL_COMMAND_OBJECT() {
                return {
                    paw: '',
                    executor: {
                        name: '',
                        platform: '',
                        command: '',
                    }
                };
            },

            getUsage() {
                if (this.docs) {
                    this.docs.forEach((obj) => {
                        if (obj) {
                            let items = obj.split('{')[1].split(': ');
                            this.usage[items[0]] = items[1];
                        }
                    });
                }
            },

            get showNotRepeatableText() {
                return !this.selectedOperation?.adversary?.has_repeatable_abilities;
            },

            get selectedOperationID() {
                return this.selectedOperation ? this.selectedOperation.id : null;
            },

            get selectedAgent() {
                if (!this.selectedOperation || this.selectedAgentIndex >= this.selectedOperation.host_group.length) return null;
                return this.selectedOperation.host_group[this.selectedAgentIndex];
            },

            get selectedAgentExecutors() {
                if (!this.selectedAgent) return [];
                return this.selectedAgent.executors.map((e) => {
                    let cmd = `(${e})`;
                    if (e in this.EXECUTOR_SHELLS) cmd += ` ${this.EXECUTOR_SHELLS[e]}`;
                    return { executor: e, display: `${cmd} > ` };
                });
            },

            get isOperationRunning() {
                if (!this.selectedOperation) return false;
                return !(this.selectedOperation.state === 'finished' || this.selectedOperation.state === 'cleanup' || this.selectedOperation.state === 'out_of_time');
            },

            get isLinkEditable() {
                if (!this.selectedLink) return false;
                // Link can only be editable if operation is running, and if link is paused, queued, or completed
                return this.isOperationRunning && ((this.selectedLink.status === -1 || !(this.selectedLink.status in this.LINK_STATUSES))
                    && !(this.selectedLink.finish.length > 0 || this.selectedLink.output === 'True'));
            },

            getOperationsMenuCaretDisplay() {
                const el = document.querySelector('.operation-menu-container');
                if (el) this.showOperationsMenuCaret = el.scrollWidth > el.offsetWidth;
            },

            getReadableTime(date) {
                // i.e. format 2021-08-03 19:37:08
                if (!date) return '';
                date = date.replace('T', ' ').replace('Z', '');
                let split = date.split('-');

                let hMonth = Number(split[1]) - 1;
                let hDate = Number(split[2].split(' ')[0]);
                let hTime = split[2].split(' ')[1].split(':');

                return new Date(Date.UTC(split[0], hMonth, hDate, hTime[0], hTime[1], hTime[2])).toLocaleString('en-US', { timeZoneName: 'short' });
            },

            getLastDecideTime() {
                if (!this.selectedOperation || !this.selectedOperation.chain || this.selectedOperation.chain.length === 0) return '';
                return getHumanFriendlyTimeISO8601(this.selectedOperation.chain[this.selectedOperation.chain.length - 1].decide);
            },

            // Controls whether user can add link or not--depending on whether adversary allows repeatable abilities, and ability has been added already or not
            isLinkAvailable(ability) {
                return this.selectedOperation.adversary.has_repeatable_abilities ? true : !this.addedTechniquesIDs.has(ability.technique_id);
            },

            generateAddedLinksList() {
                this.addedTechniquesIDs = new Set();
                this.selectedOperation.chain.forEach((link) => {
                    if (!this.addedTechniquesIDs.has(link.ability.technique_id)) this.addedTechniquesIDs.add(link.ability.technique_id);
                });
            },

            //
            // API CALLS
            //

            async initOperations() {
                this.getOperations();
                this.getFields();
                this.getUsage();

                while (this.$refs.operationsHeader) {
                    await sleep(3000);
                    this.getOperations();
                    this.getOperationsMenuCaretDisplay(); // wait for UI changes to get accurate width calcs
                    this.getAndCompareOperation();
                }
            },

            getFields() {
                Promise.all([apiV2('GET', '/api/v2/obfuscators'), apiV2('GET', '/api/v2/planners'), apiV2('GET', '/api/v2/adversaries'), apiV2('GET', '/api/v2/sources')]).then(([o, p, a, s]) => {
                    this.OBFUSCATORS = o;
                    this.PLANNERS = p;
                    this.ADVERSARIES = a;
                    this.SOURCES = s;
                }).catch((error) => {
                    console.error(error);
                });
            },

            getOperations() {
                apiV2('GET', this.ENDPOINT).then((res) => {
                    this.operations = res;
                    this.filterOperations(this.searchInput);
                }).catch(() => {
                    toast('Error getting operations');
                });
            },

            getOperation() {
                if (this.selectedOperationID) {
                    apiV2('GET', `${this.ENDPOINT}/${this.selectedOperationID}`).then((res) => {
                        this.selectedOperation = res;
                        this.generateAddedLinksList();
                    }).catch(() => {
                        toast('Error getting operation');
                    });
                } else {
                    toast('Select a valid operation to view.');
                }
            },

            getAndCompareOperation() {
                if (this.selectedOperationID) {
                    apiV2('GET', `${this.ENDPOINT}/${this.selectedOperationID}`).then((res) => {
                        if (this.selectedLink) {
                            this.selectedOperation = {
                                ...res,
                                chain: res.chain.map(link => link.id === this.selectedLink.id ? this.selectedLink : link)
                            };
                        } else {
                            this.selectedOperation = res;
                        }
                        this.generateAddedLinksList();
                    }).catch(() => {
                        console.error('Error getting operation');
                    });
                }
            },

            addOperation(isQuickAdd = false, startOperation) {
                if (isQuickAdd) startOperation.name = this.searchInput;
                if (!startOperation.name) {
                    toast('Error: Operation name field is empty.');
                } else {
                    startOperation.autonomous = Number(startOperation.autonomous);
                    startOperation.use_learning_parsers = parseInt(startOperation.use_learning_parsers, 10) === 1;
                    startOperation.auto_close = parseInt(startOperation.auto_close, 10) === 1;

                    apiV2('POST', this.ENDPOINT, startOperation)
                        .then((res) => {
                            toast(`Started operation ${startOperation.name}!`, true);
                            this.getOperations();
                            this.selectedOperation = res;
                            this.openModal = null;
                            toast('Notice that you can pause or stop the operation at any time. Toggle into manual mode if you want full control or click potential links to add TTPs to the operation.', true);
                        }).catch(() => {
                        toast('Error adding operation');
                    });
                }
            },

            deleteOperation() {
                apiV2('DELETE', `${this.ENDPOINT}/${this.selectedOperationID}`)
                    .then(() => {
                        if (this.filteredOperations.length > 1) this.selectedOperation = this.filteredOperations.find((op) => op.id !== this.selectedOperationID);
                        else this.selectedOperation = null;
                        this.getOperations();
                        toast('Deleted operation.', true);
                    })
                    .catch(() => {
                        toast('Error deleting operation.');
                    });
            },

            getAgent(agentPaw) {
                apiV2('GET', `api/v2/agents/${agentPaw}`)
                    .then((res) => {
                        // Check if agent has been seen in the last hour
                        if ((new Date() - new Date(res.last_seen)) > 3600000) {
                            toast(`Command might not run. Is Agent #${res.paw} still alive?`);
                        } else {
                            this.potentialLink.agent = res;
                        }
                    })
                    .catch(() => {
                        toast('Error getting agent.');
                    });
            },

            getAgents() {
                apiV2('GET', 'api/v2/agents')
                    .then((res) => {
                        this.updateAgentGroups(res);
                        this.selectedAgentIndex = 0;
                    })
                    .catch(() => {
                        toast('Error getting agents.');
                    });
            },

            getAbilities() {
                apiV2('GET', '/api/v2/abilities').then((abilities) => {
                    this.abilities = abilities;
                    if (!this.potentialLink.agent && this.selectedOperation.host_group && this.selectedOperation.host_group.length > 0) {
                        this.potentialLink.agent = this.selectedOperation.host_group[0];
                        this.potentialLink.executor = this.potentialLink.agent.executors[0];
                    }
                    this.getAgent(this.potentialLink.agent.paw);
                    this.filterAbilities(abilities);
                    this.tacticFiltersList = sortAlphabetically([...new Set(abilities.flatMap((a) => a.tactic))]);
                    this.techniqueFiltersList = sortAlphabetically([...new Set(abilities.flatMap((a) => a.technique_name))]);
                }).catch(() => {
                    toast('Error getting abilities', false);
                });
            },

            addManualCommand(manualCommand) {
                if (!manualCommand.executor.command) {
                    toast('Enter manual command.');
                    return;
                }
                manualCommand.paw = this.selectedAgent.paw;
                manualCommand.executor.name = document.getElementById('manual-executors').selectedOptions[0].value;
                manualCommand.executor.platform = this.selectedAgent.platform;

                if (this.selectedOperation.state === 'paused') {
                    toast('Operation is currently paused, and new links might not be added.', true);
                    this.addNewRow = false;
                }
                apiV2('POST', `${this.ENDPOINT}/${this.selectedOperationID}/potential-links`, manualCommand)
                    .then((res) => {
                        toast('Added manual command.', true);
                        this.getOperation();

                        // Reset
                        this.addNewRow = false;
                        this.selectedAgentIndex = null;
                    })
                    .catch(() => toast('Error adding manual command.'));
            },

            addPotentialLink(link) {
                if (this.selectedOperation.state === 'paused') {
                    toast('Operation is currently paused, and new links might not be added.', true);
                }
                const executor = link.executors.find((e) => this.potentialLink.executor === e.name);
                apiV2('POST', `${this.ENDPOINT}/${this.selectedOperationID}/potential-links`, {
                    ability: link,
                    paw: this.potentialLink.agent.paw,
                    executor: executor
                })
                    .then(() => {
                        toast('Added potential link.', true);
                        this.getOperation();
                        this.addedTechniquesIDs.add(link.technique_id);
                    })
                    .catch(() => {
                        toast('Error adding potential link.');
                    });
            },

            getLink(link) {
                apiV2('GET', `${this.ENDPOINT}/${this.selectedOperationID}/links/${link.id}`)
                    .then((res) => {
                        this.getLinkResults(res.output, link);
                        if (res.facts) {
                            this.selectedLinkFacts = Array.from(new Set(res.facts)).sort((a, b) => b.score - a.score);
                        }
                        this.selectedLinkCommand = b64DecodeUnicode(res.command);
                        this.editableCommand = b64DecodeUnicode(res.command);
                    })
                    .catch(() => {
                        this.selectedLinkResults = null;
                        this.selectedLinkFacts = null;
                        this.selectedLinkCommand = null;
                        toast('Error getting link results.');
                    });
            },

            getLinkResults(output, link) {
                if (output !== 'True') {
                    this.selectedLinkResults = null;
                } else {
                    apiV2('GET', `${this.ENDPOINT}/${this.selectedOperationID}/links/${link.id}/result`).then((res) => {
                        this.selectedLinkResults = b64DecodeUnicode(res.result);
                    }).catch(() => console.error('Error getting link results.'));
                }
            },

            updateLink(status, command = null) {
                const updateLink = { ...this.selectedLink, command: b64DecodeUnicode(this.selectedLink.command) };
                if (command) {
                    updateLink.command = command;
                }
                updateLink.status = status;
                apiV2('PATCH', `${this.ENDPOINT}/${this.selectedOperationID}/links/${this.selectedLink.id}`, updateLink)
                    .then((res) => {
                        this.getOperation();
                        toast(`Updating link status to: ${this.LINK_STATUSES[status]}`, true);
                    })
                    .catch(() => toast('Error updating link state.'));
            },

            updateOperation(field, updateValue) {
                this.selectedOperation[field] = updateValue;
                apiV2('PATCH', `${this.ENDPOINT}/${this.selectedOperationID}`, this.selectedOperation)
                    .then((res) => {
                        this.selectedOperation = res;
                        this.selectedLink = null;
                    })
                    .catch(() => {
                        toast(`Error updating operation ${field}. Operation may have already finished running.`);
                    });
            },

            updateOperationState() {
                if (this.selectedOperationID) {
                    apiV2('GET', `${this.ENDPOINT}/${this.selectedOperationID}`).then((res) => {
                        this.selectedOperation.state = res.state;
                        // toast('Go to the GameBoard plugin to see if the blue team can detect your activities.', true);
                    }).catch(() => {
                        toast('Error getting operation state');
                    });
                }
            },

            downloadInfo(formatType) {
              const endpoint = formatType === 'full-report' ? 'report' : formatType;
                apiV2('POST', `${this.ENDPOINT}/${this.selectedOperationID}/${endpoint}`, { enable_agent_output: this.isAgentOutputSelected })
                  .then((res) => {
                    this.createDownloadReport(res, `${this.selectedOperation.name}_${formatType}`);
                  })
                  .catch(() => toast(`Error generating operation ${formatType.replace('-', ' ')}`));
            },

            downloadCSV() {
                const csv = [];
                const rows = document.querySelector('#operationsPage').querySelectorAll('table tr:not(.csv-exclude)');

                rows.forEach((row, i) => {
                    const cols = row.querySelectorAll('td:not(.csv-exclude), th:not(.csv-exclude)');
                    const rowItems = [];
                    cols.forEach((col) => {
                        const link = this.selectedOperation.chain[i - 1];
                        if (col.className.includes('agentDetails')) {
                            let agentDetails = `Agent #${link.paw}`;
                            if (link.host) agentDetails += `\nHost: ${link.host}`;
                            if (link.pid) agentDetails += `\nPid: ${link.pid}`;
                            rowItems.push(`"${agentDetails}"`);
                        } else if (col.className.includes('commandDetails')) {
                            rowItems.push(`"${b64DecodeUnicode(link.command)}"`);
                        } else if (col.className.includes('outputDetails')) {
                            rowItems.push(`"${link.facts}"`);
                        } else {
                            rowItems.push(`"${col.innerText}"`);
                        }
                    });
                    csv.push(rowItems.join(','));
                });
                this.createDownloadReport(new Blob([csv.join('\n')], { type: 'text/csv' }), this.selectedOperation.name, true);
            },

            handleDownload() {
                if (this.selectedReportType === 'full-report') this.downloadInfo('full-report');
                else if (this.selectedReportType === 'event-logs') this.downloadInfo('event-logs');
                else if (this.selectedReportType === 'csv') this.downloadCSV();
            },

            //
            // OBJECT MANIPULATION
            //

            createDownloadReport(data, fileName, isCSV = false) {
                let dataURL;

                if (!isCSV) {
                    dataURL = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(data, null, 2))}`;
                    fileName += '.json';
                } else {
                    dataURL = window.URL.createObjectURL(data);
                    fileName += '.csv';
                }

                const elem = document.createElement('a');
                elem.setAttribute('href', dataURL);
                elem.setAttribute('download', fileName);
                elem.click();
            },

            updateAgentGroups(agents) {
                if (agents) {
                    agents.forEach((agent) => {
                        if (!this.agentGroups.includes(agent.group)) this.agentGroups.push(agent.group);
                    });
                }
            },

            validateJitter(startOperation, newValue = '') {
                if (!newValue.includes('/')) return false;
                let [jitterMin, jitterMax] = newValue.split('/');
                jitterMin = parseInt(jitterMin, 10);
                jitterMax = parseInt(jitterMax, 10);

                if (jitterMin < 0 || jitterMax < 0) {
                    toast(`Error: Jitter ${!jitterMin ? 'MIN' : 'MAX'} must be valid.`);
                    return false;
                }
                if (jitterMin >= jitterMax) {
                    toast('Error: Jitter MIN must be less than the jitter MAX.');
                    return false;
                }

                startOperation.jitter = newValue;
                return true;
            },

            filterOperations(userInput) {
                this.searchInput = userInput;
                this.filteredOperations = this.operations.filter((op) => op.name.includes(userInput)).sort((a, b) => {
                    let c = new Date(a.start);
                    let d = new Date(b.start);
                    return d - c;
                }); // Filter and sort by start time (newest -> oldest)
                this.getOperationsMenuCaretDisplay();
            },

            filterAbilities(abilities) {
                this.filteredAbilitiesList = abilities.filter((ability) => {
                    let matchAgent = true, matchTactic = true, matchTechnique = true;
                    if (this.potentialLink.executor) matchAgent = ability.executors.some((ex) => ex.platform === this.potentialLink.agent.platform && this.potentialLink.executor === ex.name);
                    if (this.potentialLink.tactic) matchTactic = this.potentialLink.tactic === ability.tactic;
                    if (this.potentialLink.technique) matchTechnique = this.potentialLink.technique === ability.technique_name;
                    return matchAgent && matchTactic && matchTechnique;
                });
            },
        };
    }
</script>

<style>
    :scope {
        --dark-gray: gray;
        --light-gray: #e6e6e6;
        --decisions-color: #4fdcfc;
    }

    #operationsPage .white-space-pre-line {
        white-space: pre-line;
        word-wrap: break-word;
    }

    #operationsPage .ellipsis-divider {
        text-align: center;
        font-size: 0.3em;
    }

    #operationsPage .ellipsis-divider em {
        color: #484747;
        padding: 0 7em;
    }

    #operationsPage span.decisionsIcon {
        font-size: x-small;
        font-weight: 500;
        font-family: sans-serif;
        position: relative;
        top: -21px;
        left: 35%;
        color: var(--decisions-color);
    }

    #operationsPage .decisionsDisplay {
        color: var(--decisions-color) !important;
    }

    #operationsPage .operation-menu-container {
        overflow-x: scroll;
        overflow-y: hidden;
    }

    #operationsPage .operation-menu-links {
        color: white;
        margin-right: 2em;
        text-align: left;
        cursor: pointer;
        display: flex;
        justify-content: flex-start;
        align-items: center;
        width: 5em;
        flex-flow: column wrap;
        padding: 10px;
    }

    #operationsPage .operation-menu-links .readable-time {
        width: 5em;
        text-align: center;
        color: gray;
    }

    #operationsPage .operation-menu-links .operation-name {
        max-width: 100%;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
    }

    #operationsPage .operation-menu-links em {
        font-size: 3em;
        padding-bottom: 5px;
        min-width: 35px;
    }

    #operationsPage .modal-card {
        max-height: 90vh;
    }

    #operationsPage .width-100 {
        width: 100% !important;
    }

    #operationsPage .column {
        margin: 0;
    }

    /*MODAL FORM STYLE*/
    #operationsPage .modal-form-fields.download-buttons-container button {
        width: fit-content;
    }

    #operationsPage .modal-results {
        overflow-x: hidden;
        overflow-y: scroll;
        height: 50vh;
    }

    #operationsPage .modal-results li.abilities-list-item {
        box-sizing: border-box;
        padding: .5em;
        list-style: none;
    }

    #operationsPage .modal-results li.abilities-list-item:hover {
        background-color: rgba(255, 255, 255, 0.1);
    }

    /*END MODAL FORM STYLE*/

    #operationsPage span.output-container {
        height: 8em;
        display: block;
        overflow: hidden;
        white-space: pre-line;
        max-width: 25ch;
    }

    #operationsPage .cursor-pointer:hover {
        cursor: pointer;
    }

    #operationsPage .timeline-table .modal-card code, table code, .modal-form code {
        color: #ff8181;
        background-color: initial;
        white-space: pre-line;
    }

    #operationsPage .timeline-table table .highlight {
        width: fit-content !important;
    }

    #operationsPage .timeline-table {
        padding-bottom: 5em;
    }

    #operationsPage .timeline-table table tr th {
        font-weight: 400;
        font-size: 0.75rem;
        border-bottom: none;
        color: gray;
    }

    #operationsPage .button:active, .button.is-active, .button:focus, .button.is-focused {
        color: inherit;
    }

    #operationsPage button.is-larger {
        font-size: 2.1rem;
    }

    #operationsPage .linkActionsColumn button[disabled] {
        background-color: transparent;
    }

    #operationsPage button.no-style {
        background-color: transparent;
        border: none;
        box-shadow: none;
    }

    #operationsPage button.no-style.reset {
        padding: 0.5em;
        width: fit-content;
        font-size: .75em;
    }

    #operationsPage button.no-style[disabled] {
        background-color: initial !important;
    }

    #operationsPage .caret-button {
        font-size: 1em;
        padding-bottom: 0;
        margin-top: -30px;
    }

    #operationsPage .scroll-more-caret {
        color: gray;
    }

    #operationsPage button.no-style:hover {
        border: none;
        color: white;
        transform: scale(1.2);
    }

    #operationsPage em sub {
        font-family: sans-serif;
    }

    #operationsPage .operations-menu-set-width {
        width: 45%;
    }

    #operationsPage .operations-dashboard {
        width: 100%;
        justify-content: space-between;
        overflow-y: scroll;
        margin-bottom: 1em;
    }

    #operationsPage .controls-container button {
        margin: 0 2rem;
        padding: 0;
        max-height: 34px;
    }

    #operationsPage .timeline-table table th.header {
        border-bottom: none;
    }

    #operationsPage .timeline-table th:not(.decideColumn), th:not(.statusColumn) {
        text-align: left;
    }

    #operationsPage .timeline-table .decideColumn {
        color: gray;
        width: 120px;
        word-break: break-word;
        font-size: 0.75rem;
        text-align: center !important;
    }

    #operationsPage .timeline-table .infoColumn {
        width: 200px;
    }

    #operationsPage .timeline-table table tbody td {
        vertical-align: middle;
        border: none;
        height: 5.5em;
    }

    #operationsPage .timeline-table table tbody td.linkActionsColumn {
        display: flex;
        align-items: center;
        flex-flow: row-reverse;
        padding-bottom: 0;
    }

    #operationsPage .timeline-table table tbody td.commandDetails textarea {
        color: #ff8181;
        background-color: #262626;
        height: 150px;
        max-width: 22ch;
        word-break: break-word;
        padding: 5px;
        border-radius: 5px;
    }

    #operationsPage .timeline-table table tbody td textarea[contenteditable] {
        width: 100%;
        height: 5em;
        margin-top: 1em;
    }

    #operationsPage .timeline-table table tbody td.commandDetails button {
        width: max-content;
    }

    #operationsPage .timeline-table table tbody tr.linkEditCommandRow td:last-child {
        display: flex;
        justify-content: space-around;
        padding: 0;
        flex-flow: row;
        align-items: center;
        background-color: #2b2929;
        border-radius: 2px;
    }

    #operationsPage .timeline-table table tbody tr.linkEditCommandRow textarea {
        border-radius: 2px;
        line-height: 0.75rem;
        width: 10rem;
    }

    #operationsPage .timeline-table table tbody tr.linkEditCommandRow .linkEditControls {
        display: flex;
        flex-flow: row wrap;
        justify-content: flex-end;
        align-items: center;
    }

    #operationsPage .timeline-table table tfoot td {
        padding-top: 1em;
        border: none !important;
    }

    /*gray timeline*/
    #operationsPage span.linkStatus {
        justify-content: flex-start;
        display: flex;
    }

    #operationsPage span.linkStatus::before {
        width: 2px;
        height: 180px;
        background-color: white;
        content: "";
        display: inline-block;
        position: absolute;
        margin-left: 25px;
        margin-top: 40px;
    }

    /*circle for event*/
    #operationsPage span.linkStatus::after {
        position: relative;
        display: block;
        background: #161616;
        border-radius: 50%;
        height: 50px;
        width: 50px;
        content: attr(data-content);
        padding-top: 18px;
        text-align: center;
        font-size: 0.5em;
    }

    #operationsPage span.status {
        position: relative;
        top: 55px;
        z-index: 10;
        font-size: .5em;
        color: white;
        left: 15px;
        display: flex;
    }

    /*queued*/
    #operationsPage span.status-queued {
        color: #555;
    }

    #operationsPage span.status-queued::after {
        box-shadow: 0 0 0 0.2em #555;
    }

    /*success*/
    #operationsPage span.status-success {
        color: #4a9;
    }

    #operationsPage span.status-success::after {
        box-shadow: 0 0 0 0.2em #4a9;
    }

    /*failure*/
    #operationsPage span.status-failed {
        color: #c31;
    }

    #operationsPage span.status-failed::after {
        box-shadow: 0 0 0 0.2em #c31;
    }

    /*paused*/
    #operationsPage span.status-paused {
        color: #ffc500;
    }

    #operationsPage span.status-paused::after {
        box-shadow: 0 0 0 0.2em #ffc500;
    }

    /*removed*/
    #operationsPage span.status-discarded {
        color: #a05195;
    }

    #operationsPage span.status-discarded::after {
        box-shadow: 0 0 0 0.2em #a05195;
    }

    /*collected*/
    #operationsPage span.status-collect {
        color: #ffb000;
    }

    #operationsPage span.status-collect::after {
        box-shadow: 0 0 0 0.2em #ffb000;
    }

    /*untrusted*/
    #operationsPage span.status-untrusted {
        color: white;
    }

    #operationsPage span.status-untrusted::after {
        box-shadow: 0 0 0 0.2em white;
    }

    /*visible*/
    #operationsPage span.status-visible {
        color: #f012be;
    }

    #operationsPage span.status-visible::after {
        box-shadow: 0 0 0 0.2em #f012be;
    }

    /*timeout*/
    #operationsPage span.status-timeout {
        color: cornflowerblue;
    }

    #operationsPage span.status-timeout::after {
        box-shadow: 0 0 0 0.2em cornflowerblue;
    }
</style>
